// SPDX-License-Identifier: GPL-2.0
#include "ax_utils.h"

#include <linux/sched.h>
#include <linux/wait.h>

int axvu_wait_init(os_wait_t *wait)
{
	wait_queue_head_t *wq = NULL;


	if (wait == NULL) {
		ax_err(1, "%s - parameter invalid!\n", __func__);
		return -1;
	}
	wq = (wait_queue_head_t *) axvu_kmalloc(sizeof(wait_queue_head_t),
			os_gfp_kernel);
	if (wq == NULL) {
		ax_err(1, "%s - axvu_kmalloc error!\n", __func__);
		return -1;
	}
	init_waitqueue_head(wq);
	wait->wait = wq;

	return 0;
}

int axvu_wait_interruptible(os_wait_t *wait, os_wait_cond_func_t func,
	void *param)
{
	wait_queue_head_t *wq = NULL;
	long ret = 0;

	if (wait == NULL) {
		ax_err(1, "%s - parameter invalid!\n", __func__);
		return -1;
	}

	if (func == NULL) {
		ax_err(1, "%s - func invalid!\n", __func__);
		return -1;
	}

	wq = (wait_queue_head_t *)(wait->wait);
	if (wq == NULL) {
		ax_err(1, "%s - wait->wait is NULL!\n", __func__);
		return -1;
	}

	ret = wait_event_interruptible(*wq, func(param));

	return ret;
}

int axvu_wait_uninterruptible(os_wait_t *wait, os_wait_cond_func_t func,
	void *param)
{
	wait_queue_head_t *wq = NULL;
	long ret = 0;

	if (wait == NULL) {
		ax_err(1, "%s - parameter invalid!\n", __func__);
		return -1;
	}

	if (func == NULL) {
		ax_err(1, "%s - func invalid!\n", __func__);
		return -1;
	}

	wq = (wait_queue_head_t *)(wait->wait);
	if (wq == NULL) {
		ax_err(1, "%s - wait->wait is NULL!\n", __func__);
		return -1;
	}

	wait_event(*wq, func(param));

	return ret;
}

int axvu_wait_timeout_interruptible(os_wait_t *wait, os_wait_cond_func_t func,
	void *param, unsigned long timeout_ms)
{
	wait_queue_head_t *wq = NULL;
	long ret = timeout_ms;

	if (wait == NULL) {
		ax_err(1, "%s - parameter invalid!\n", __func__);
		return -1;
	}

	if (func == NULL) {
		ax_err(1, "%s - func invalid!\n", __func__);
		return -1;
	}

	wq = (wait_queue_head_t *)(wait->wait);
	if (wq == NULL) {
		ax_err(1, "%s - wait->wait is NULL!\n", __func__);
		return -1;
	}

	ret = wait_event_interruptible_timeout(*wq, func(param),
			msecs_to_jiffies(timeout_ms));

	return ret;
}

int axvu_wait_timeout_uninterruptible(os_wait_t *wait, os_wait_cond_func_t func,
	void *param, unsigned long timeout_ms)
{
	wait_queue_head_t *wq = NULL;
	long ret = timeout_ms;

	if (wait == NULL) {
		ax_err(1, "%s - parameter invalid!\n", __func__);
		return -1;
	}

	if (func == NULL) {
		ax_err(1, "%s - func invalid!\n", __func__);
		return -1;
	}

	wq = (wait_queue_head_t *)(wait->wait);
	if (wq == NULL) {
		ax_err(1, "%s - wait->wait is NULL!\n", __func__);
		return -1;
	}

	ret = wait_event_timeout(*wq, func(param),
			msecs_to_jiffies(timeout_ms));

	return ret;
}

void axvu_wakeup(os_wait_t *wait)
{
	wait_queue_head_t *wq = NULL;

	wq = (wait_queue_head_t *)(wait->wait);
	if (wq == NULL) {
		ax_err(1, "%s - wait->wait is NULL!\n", __func__);
		return;
	}
	wake_up_all(wq);
}

void axvu_wait_destroy(os_wait_t *wait)
{
	wait_queue_head_t *wq = NULL;

	wq = (wait_queue_head_t *)(wait->wait);
	if (wq == NULL) {
		ax_err(1, "%s - wait->wait is NULL!\n", __func__);
		return;
	}
	axvu_kfree(wq);
	wait->wait = NULL;
}

